package br.edu.universo.si.projeto2.infojob.server.persistencia;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

import br.edu.universo.si.projeto2.infojob.client.bean.BeanAssinante;
import br.edu.universo.si.projeto2.infojob.client.bean.BeanMensagem;
import br.edu.universo.si.projeto2.infojob.server.Database;

/**
 * Classe de persistência de mensagens.
 * @author Andrey A. de Oliveira
 */
public class PMensagens
{
	/**
	 * Busca todas as mensagens da CX. de Entrada de um ID.
	 * @author Andrey A. de Oliveira
	 * @param idDestinatario
	 * @return ArrayList<BeanMensagem> : lista de todas as mensagens.
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 */
	public static ArrayList<BeanMensagem> getMensagensCaixaEntrada(Integer idDestinatario)
		throws ClassNotFoundException, SQLException
	{
		ArrayList<BeanMensagem> clMensagens = new ArrayList<BeanMensagem>();
		Database database = Database.getInstance();

		PreparedStatement pStmt = 
			database.getPreparedStatement("SELECT * FROM infojob.tb_caixa_entrada WHERE id_destinatario = ?; ");

		pStmt.setInt(1, idDestinatario);

		ResultSet rs = pStmt.executeQuery();

		while(rs.next())
		{
			BeanMensagem mensagem = new BeanMensagem();

			mensagem.setId(rs.getInt("id"));
			mensagem.setAssunto(rs.getString("assunto"));
			mensagem.setMensagem(rs.getString("mensagem"));
			mensagem.setDataEnvio(rs.getString("data_envio"));
			mensagem.setLida(rs.getBoolean("lida"));

			clMensagens.add(mensagem);
		}

		return clMensagens;
	}

	/**
	 * Busca todas as mensagens da CX. de saída.
	 * @author Andrey A. de Oliveira
	 * @param idRemetente
	 * @return ArrayList<BeanMensagem> : lista de mensagens.
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 */
	public static ArrayList<BeanMensagem> getMensagensCaixaSaida(Integer idRemetente) throws ClassNotFoundException, SQLException
	{
		ArrayList<BeanMensagem> clMensagens = new ArrayList<BeanMensagem>();
		Database database = Database.getInstance();

		PreparedStatement pStmt = 
			database.getPreparedStatement("SELECT * FROM infojob.tb_caixa_saida WHERE id_remetente = ?; ");

		pStmt.setInt(1, idRemetente);

		ResultSet rs = pStmt.executeQuery();

		while(rs.next())
		{
			BeanMensagem mensagem = new BeanMensagem();

			mensagem.setId(rs.getInt("id"));
			mensagem.setAssunto(rs.getString("assunto"));
			mensagem.setMensagem(rs.getString("mensagem"));
			mensagem.setDataEnvio(rs.getString("data_envio"));
			mensagem.setLida(rs.getBoolean("lida"));

			clMensagens.add(mensagem);
		}

		return clMensagens;
	}

	/**
	 * Exclui uma mensagem da Caixa de Entrada.
	 * @author Andrey A. de Oliveira
	 * @param idMensagem
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 */
	public static void excluirMensagemCxEntrada(Integer idMensagem) throws ClassNotFoundException, SQLException
	{
		Database database = Database.getInstance();
		
		PreparedStatement pStmt = database.getPreparedStatement("DELETE FROM infojob.tb_caixa_entrada WHERE id = ?; ");
		pStmt.setInt(1, idMensagem);

		pStmt.executeUpdate();
	}

	/**
	 * Exclui mensagens da Caixa de Entrada.
	 * @author Andrey A. de Oliveira
	 * @param clMensagens
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 */
	public static void excluirMensagensCxEntrada(ArrayList<BeanMensagem> clMensagens) throws ClassNotFoundException, SQLException
	{
		Database database = Database.getInstance();

		for (BeanMensagem mensagem : clMensagens)
		{
			PreparedStatement pStmt = database.getPreparedStatement("DELETE FROM infojob.tb_caixa_entrada WHERE id = ?; ");
			pStmt.setInt(1, mensagem.getId());

			pStmt.executeUpdate();			
		}
	}

	/**
	 * Exclui mensagens da Caixa de Entrada com controle transacional.
	 * @author Andrey A. de Oliveira
	 * @param conn
	 * @param clMensagens
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 */
	public static void excluirMensagensCxEntrada(Connection conn, ArrayList<BeanMensagem> clMensagens) throws ClassNotFoundException, SQLException
	{
		Database database = Database.getInstance();

		for (BeanMensagem mensagem : clMensagens)
		{
			PreparedStatement pStmt = database.getPreparedStatement(conn, "DELETE FROM infojob.tb_caixa_entrada WHERE id = ?; ");
			pStmt.setInt(1, mensagem.getId());

			pStmt.executeUpdate();			
		}
	}

	/**
	 * Exclui uma mensagen da Caixa de Saída.
	 * @author Andrey A. de Oliveira
	 * @param idMensagem
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 */
	public static void excluirMensagemCxSaida(Integer idMensagem) throws ClassNotFoundException, SQLException
	{
		Database database = Database.getInstance();
		
		PreparedStatement pStmt = database.getPreparedStatement("DELETE FROM infojob.tb_caixa_saida WHERE id = ?; ");
		pStmt.setInt(1, idMensagem);

		pStmt.executeUpdate();
	}

	/**
	 * Exclui mensagens da Caixa de Saída.
	 * @author Andrey A. de Oliveira
	 * @param clMensagens
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 */
	public static void excluirMensagensCxSaida(ArrayList<BeanMensagem> clMensagens) throws ClassNotFoundException, SQLException
	{
		Database database = Database.getInstance();

		for (BeanMensagem mensagem : clMensagens)
		{
			PreparedStatement pStmt = database.getPreparedStatement("DELETE FROM infojob.tb_caixa_saida WHERE id = ?; ");
			pStmt.setInt(1, mensagem.getId());

			pStmt.executeUpdate();			
		}
	}

	/**
	 * Exclui mensagens da Caixa de Saída com controle transacional.
	 * @author Andrey A. de Oliveira
	 * @param conn
	 * @param clMensagens
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 */
	public static void excluirMensagensCxSaida(Connection conn, ArrayList<BeanMensagem> clMensagens) throws ClassNotFoundException, SQLException
	{
		Database database = Database.getInstance();

		for (BeanMensagem mensagem : clMensagens)
		{
			PreparedStatement pStmt = database.getPreparedStatement(conn, "DELETE FROM infojob.tb_caixa_saida WHERE id = ?; ");
			pStmt.setInt(1, mensagem.getId());

			pStmt.executeUpdate();			
		}
	}

	/**
	 * Busca uma mensagem pelo ID.
	 * @author Andrey A. de Oliveira
	 * @param id
	 * @return BeanMensagem
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 */
	public static BeanMensagem getMensagemById(Integer id) throws ClassNotFoundException, SQLException
	{
		Database database = Database.getInstance();

		BeanMensagem mensagem = new BeanMensagem();
		mensagem.setId(id);

		if (PMensagens.isInCaixaEntrada(mensagem))
		{
			PreparedStatement pStmt = database.getPreparedStatement("SELECT *, TO_CHAR(data_envio, 'dd/MM/yyyy') AS data_envio_str FROM infojob.tb_caixa_entrada WHERE id = ?; ");
			pStmt.setInt(1, id);

			ResultSet rs = pStmt.executeQuery();

			if (rs.next())
			{
				mensagem.setDataEnvio(rs.getString("data_envio_str"));
				mensagem.setAssunto(rs.getString("assunto"));
				mensagem.setMensagem(rs.getString("mensagem"));
				
				if (PProfissional.isProfissional(rs.getInt("id_remetente")))
				{
					mensagem.setRemetente(PProfissional.getProfissionalById(rs.getInt("id_remetente")));
				}
				else if (PEmpresa.isEmpresa(rs.getInt("id_remetente")))
				{
					mensagem.setRemetente(PEmpresa.getEmpresaById(rs.getInt("id_remetente")));
				}

				if (PProfissional.isProfissional(rs.getInt("id_destinatario")))
				{
					mensagem.setDestinatario(PProfissional.getProfissionalById(rs.getInt("id_destinatario")));
				}
				else if (PEmpresa.isEmpresa(rs.getInt("id_destinatario")))
				{
					mensagem.setDestinatario(PEmpresa.getEmpresaById(rs.getInt("id_destinatario")));
				}
			}
			
			return mensagem;
		}
		else if (PMensagens.isInCaixaSaida(mensagem))
		{
			PreparedStatement pStmt = database.getPreparedStatement("SELECT *, TO_CHAR(data_envio, 'dd/MM/yyyy') AS data_envio_str FROM infojob.tb_caixa_saida WHERE id = ?; ");
			pStmt.setInt(1, id);

			ResultSet rs = pStmt.executeQuery();

			if (rs.next())
			{
				mensagem.setDataEnvio(rs.getString("data_envio_str"));
				mensagem.setAssunto(rs.getString("assunto"));
				mensagem.setMensagem(rs.getString("mensagem"));
				
				if (PProfissional.isProfissional(rs.getInt("id_remetente")))
				{
					mensagem.setRemetente(PProfissional.getProfissionalById(rs.getInt("id_remetente")));
				}
				else if (PEmpresa.isEmpresa(rs.getInt("id_remetente")))
				{
					mensagem.setRemetente(PEmpresa.getEmpresaById(rs.getInt("id_remetente")));
				}

				if (PProfissional.isProfissional(rs.getInt("id_destinatario")))
				{
					mensagem.setDestinatario(PProfissional.getProfissionalById(rs.getInt("id_destinatario")));
				}
				else if (PEmpresa.isEmpresa(rs.getInt("id_destinatario")))
				{
					mensagem.setDestinatario(PEmpresa.getEmpresaById(rs.getInt("id_destinatario")));
				}
			}
			
			return mensagem;
		}

		return null;
	}

	/**
	 * Verifica se a mensagem está ou não na Caixa de Entrada. 
	 * @author Andrey A. de Oliveira
	 * @param mensagem
	 * @return boolean
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 */
	private static boolean isInCaixaEntrada(BeanMensagem mensagem) throws ClassNotFoundException, SQLException
	{
		Database database = Database.getInstance();

		PreparedStatement pStmt = database.getPreparedStatement("SELECT * FROM infojob.tb_caixa_entrada WHERE id = ?; ");
		pStmt.setInt(1, mensagem.getId());

		ResultSet rs = pStmt.executeQuery();

		if (rs.next())
		{
			return true;
		}

		return false;
	}

	/**
	 * Verifica se uma mensagem está na Caixa de Saída.
	 * @author Andrey A. de Oliveira
	 * @param mensagem
	 * @return boolean.
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 */
	private static boolean isInCaixaSaida(BeanMensagem mensagem) throws ClassNotFoundException, SQLException
	{
		Database database = Database.getInstance();

		PreparedStatement pStmt = database.getPreparedStatement("SELECT * FROM infojob.tb_caixa_saida WHERE id = ?; ");

		pStmt.setInt(1, mensagem.getId());

		ResultSet rs = pStmt.executeQuery();

		if (rs.next())
		{
			return true;
		}

		return false;
	}

	/**
	 * Seta uma mensagem como lida.
	 * @author Andrey A. de Oliveira
	 * @param mensagem
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 */
	public static void setMensagemLida(BeanMensagem mensagem) throws ClassNotFoundException, SQLException
	{
		Database database = Database.getInstance();

		if (isInCaixaEntrada(mensagem))
		{
			PreparedStatement pStmt = database.getPreparedStatement("UPDATE infojob.tb_caixa_entrada SET lida = true WHERE id = ?; ");
			pStmt.setInt(1, mensagem.getId());

			pStmt.executeUpdate();			
		}

		if (isInCaixaSaida(mensagem))
		{
			PreparedStatement pStmt = database.getPreparedStatement("UPDATE infojob.tb_caixa_saida SET lida = true WHERE id = ?; ");
			pStmt.setInt(1, mensagem.getId());

			pStmt.executeUpdate();			
		}

		return;
	}

	/**
	 * Envia mensagem.
	 * @author Andrey A. de Oliveira
	 * @param mensagem
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 */
	public static void enviarMensagem(BeanMensagem mensagem) throws ClassNotFoundException, SQLException
	{
		Database database = Database.getInstance();

		Connection conn = database.getConnection();
		conn.setAutoCommit(false);

		PreparedStatement pStmt = conn.prepareStatement("INSERT INTO infojob.tb_caixa_entrada(id_remetente, id_destinatario, assunto, mensagem, data_envio, lida)" +
				" VALUES(?, ?, ?, ?, CURRENT_DATE, false); ");

		pStmt.setInt(1, mensagem.getRemetente().getId());
		pStmt.setInt(2, mensagem.getDestinatario().getId());
		pStmt.setString(3, mensagem.getAssunto());
		pStmt.setString(4, mensagem.getMensagem());

		pStmt.executeUpdate();

		pStmt = conn.prepareStatement("INSERT INTO infojob.tb_caixa_saida(id_remetente, id_destinatario, assunto, mensagem, data_envio, lida)" +
				" VALUES(?, ?, ?, ?, CURRENT_DATE, true); ");

		pStmt.setInt(1, mensagem.getRemetente().getId());
		pStmt.setInt(2, mensagem.getDestinatario().getId());
		pStmt.setString(3, mensagem.getAssunto());
		pStmt.setString(4, mensagem.getMensagem());

		pStmt.executeUpdate();

		conn.commit();
	}
}